package br.usp.ime.macmovel.android;

import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

/**
 * The library map activity shows the user simple directions to several of USP's libraries.
 */
public class LibraryMapActivity extends MapActivity {
	private static final int DEFAULT_ZOOM = 15;
	private MapView map_view;
	private MapController map_controller;
	private LocationListener location_listener;
	private MyLocationOverlay my_location_overlay;
	private GeoPoint library_point;
	private int[] geo_coords;
	private List<Overlay> mapOverlays;
	private Drawable drawable;
	private USPItemizedOverlay itemizedoverlay;
	private TextView dist_lib;
	private LocationManager location_manager;
	private LineOverlay lineOverlay;
	
	/**
	 * This method sets up the map and a slider to select a library.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.library_map);
		
		dist_lib = (TextView) findViewById(R.id.dist_lib);
		
		Resources res = getResources();
		geo_coords = res.getIntArray(R.array.geo_coords);

		map_view = (MapView) findViewById(R.id.map_view);

		map_controller = map_view.getController();
		map_controller.setZoom(DEFAULT_ZOOM);

		map_view.setStreetView(true);
		map_view.displayZoomControls(true);
		map_view.setBuiltInZoomControls(true);

		library_point = new GeoPoint(geo_coords[0], geo_coords[1]);
		map_controller.setCenter(library_point);

		my_location_overlay = new MyLocationOverlay(this, map_view);
        my_location_overlay.enableMyLocation();
		map_view.getOverlays().add(my_location_overlay);
		map_view.postInvalidate();

		location_listener = new LocationListener() {

			public void onStatusChanged(String provider, int status,
					Bundle extras) {

			}

			public void onProviderEnabled(String provider) {

			}

			public void onProviderDisabled(String provider) {
				updatePosition();
			}

			public void onLocationChanged(Location location) {
				updatePosition();
			}
		};

		location_manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_COARSE);
		criteria.setAltitudeRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_HIGH);
		String provider = location_manager.getBestProvider(criteria, true);

		updatePosition();

		location_manager.requestLocationUpdates(provider, 10000, 20,
				location_listener);

		mapOverlays = map_view.getOverlays();
		drawable = this.getResources().getDrawable(
				R.drawable.ic_tab_activity3_gray);

		Spinner libraries_spinner = (Spinner) findViewById(R.id.libraries_spinner);
		configureLibrariesSpinner(libraries_spinner);
	}

	/**
	 * Configures the spinner used to select the libraries.
	 */
	private void configureLibrariesSpinner(Spinner libraries_spinner) {
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
				this, R.array.libraries_array,
				android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		libraries_spinner.setAdapter(adapter);
		libraries_spinner.setSelection(0);

		libraries_spinner
				.setOnItemSelectedListener(new OnItemSelectedListener() {

					public void onItemSelected(AdapterView<?> parent,
							View view, int pos, long id) {
						library_point = new GeoPoint(geo_coords[2 * pos],
								geo_coords[2 * pos + 1]);

						mapOverlays.remove(itemizedoverlay);

						itemizedoverlay = new USPItemizedOverlay(drawable);
						OverlayItem overlayitem = new OverlayItem(
								library_point, "", "");
						itemizedoverlay.addOverlay(overlayitem);
						mapOverlays.add(itemizedoverlay);

						map_controller.setCenter(library_point);
						
						updatePosition();
					}

					public void onNothingSelected(AdapterView<?> arg0) {
					}
				});
	}
	
	/**
	 * Calculates the distance between the user and the currently selected library.
	 */
	private float calculateDistance(GeoPoint gp1, GeoPoint gp2) {
	    double latgp1 = ((double)gp1.getLatitudeE6()) / 1e6;
	    double lnggp1 = ((double)gp1.getLongitudeE6()) / 1e6;
	    double latgp2 = ((double)gp2.getLatitudeE6()) / 1e6;
	    double lnggp2 = ((double)gp2.getLongitudeE6()) / 1e6;
	    float [] dist = new float[1];

	    Location.distanceBetween(latgp1, lnggp1, latgp2, lnggp2, dist);

	    return dist[0];
	}

	/**
	 * Updates the current position of the user. When possible the MyLocationOverlay, otherwise
	 * we use the GPS as a fallback.
	 */
	private void updatePosition() {
		String msg;
		msg = getString(R.string.distance_to_library);
		GeoPoint myLocation = my_location_overlay.getMyLocation();
		if (myLocation != null) {
			msg += calculateDistance(library_point, myLocation);
			msg += getString(R.string.meters);
			addLineOverlay(myLocation);
		}
		else {
			Location lastKnownLoc = location_manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			if (lastKnownLoc != null) {
				int lat, lng;
				lat = (int) lastKnownLoc.getLatitude() * 1000000;
				lng = (int) lastKnownLoc.getLongitude() * 1000000;
				myLocation = new GeoPoint(lat, lng);
				msg += calculateDistance(library_point, myLocation);
				msg += getString(R.string.meters);
				addLineOverlay(myLocation);
			} else {
				msg += getString(R.string.unavailable);
			}
		}
		dist_lib.setText(msg);
	}

	/**
	 * Draws a line between the user's location and the library currently selected.
	 */	
	private void addLineOverlay(GeoPoint myLocation) {
		if (lineOverlay != null)
			map_view.getOverlays().remove(lineOverlay);
		lineOverlay = new LineOverlay(myLocation, library_point);
		map_view.getOverlays().add(lineOverlay);
	}

	/**
	 * No need to display routes.
	 */
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	/**
	 * Goes back to tracking the user's location.
	 */
	@Override
	protected void onResume() {
		super.onResume();
		my_location_overlay.enableMyLocation();
	}

	/**
	 * Stops tracking the user's location to conserve energy.
	 */
	@Override
	protected void onPause() {
		super.onPause();
		my_location_overlay.disableMyLocation();
	}
}